/*
 * QObjectDelegate.h  0.4.0 / Nov 14, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
#ifndef QOBJECTDELEGATE_H
#define QOBJECTDELEGATE_H

#include "Cute4jCore.h"

// QObjectDelegate Class. ------------------------------------------------------

/*!
 * \brief Abstract QObject Delegate.
 *
 * \author Slobodan Vrkacevic
 * \version 0.4.0
 */
class CUTE4J_EXPORT QObjectDelegate : public QObject
{
  Q_OBJECT
protected:
  QObjectDelegate(JNIEnv *env, jobject jniObj, QObject *qObj);
  QObjectDelegate(JNIEnv *env, jobject jniObj);
  virtual ~QObjectDelegate();
private:
  QObjectDelegate(const QObjectDelegate &);
public:
  void setName(JNIEnv *env, jstring name);
  void postEvent(QEvent *e);
  void sendEvent(QEvent *e);
public:
  virtual void destroy(JNIEnv *env, bool notify = false);
public:
  static void initialize(JNIEnv *env, jclass cls);
protected:
  jlong delegatePointer();
  void setDelegatePointer(jlong delegatePointer);
  void setQObject(QObject *qObj);
protected:
  virtual jfieldID delegatePointerFID() const = 0;
protected slots:
  virtual void objectDestroyed(QObject *qObj);
protected:
  inline JNIObject *jniObject() const;
  inline QObject *qObject() const;
  inline bool notifyDelete() const;
  inline void setNotifyDelete(bool notifyDelete);
  inline bool connectAuto(const QObject *sender, const char *signal,
                          const char *member) const;
  inline bool connectDirect(const QObject *sender, const char *signal,
                            const char *member) const;
  inline bool connectQueued(const char *signal, const char *member) const;
  inline bool disconnect(const char *signal, const char *member);
  inline bool disconnect(const QObject *sender, const char *signal,
                         const char *member);
protected:
  inline static jmethodID disposeMID();
private:
  JNIObject *m_jniObject;
  QObject *m_qObject;
  bool m_notifyDelete;
private:
  static jmethodID sm_disposeMID;
public:
  static const char *const DELEGATE_PROPERTY_NAME;
  static const QVariant INVALID_QVARIANT;
};

// QObjectDelegate :: Protected Inline Member Functions. -----------------------

/*!
 * \brief Returns JNIObject pointer.
 *
 * \return JNIObject pointer
 */
inline JNIObject *QObjectDelegate::jniObject() const
{
  return m_jniObject;
}

/*!
 * \brief Returns QObject pointer.
 *
 * \return QObject pointer
 */
inline QObject *QObjectDelegate::qObject() const
{
  return m_qObject;
}

/*!
 * \brief Returns \c true if notifies about delete.
 *
 * \return \c true if notifies about delete
 */
inline bool QObjectDelegate::notifyDelete() const
{
  return m_notifyDelete;
}

/*!
 * \brief Sets notification on object delete.
 *
 * \return \c true if notifies
 */
inline void QObjectDelegate::setNotifyDelete(bool notifyDelete)
{
  m_notifyDelete = notifyDelete;
}

/*!
 * \brief Connects a signal and a slot of this object using AutoConnection mode.
 *
 * \param sender the sender
 * \param signal the signal
 * \param member the member
 *
 * \return \c true if succeed
 */
inline bool QObjectDelegate::connectAuto(const QObject *sender,
                                         const char *signal,
                                         const char *member) const
{
  return connect(sender, signal, this, member, Qt::AutoConnection);
}

/*!
 * \brief Connects a signal and a slot of this object using DirectConnection
 *        mode.
 *
 * \param sender the sender
 * \param signal the signal
 * \param member the member
 *
 * \return \c true if succeed
 */
inline bool QObjectDelegate::connectDirect(const QObject *sender,
                                           const char *signal,
                                           const char *member) const
{
  return connect(sender, signal, this, member, Qt::DirectConnection);
}

/*!
 * \brief Connects a signal and a slot of this object using QueuedConnection
 *        mode.
 *
 * \param signal the signal
 * \param member the member
 *
 * \return \c true if succeed
 */
inline bool QObjectDelegate::connectQueued(const char *signal,
                                           const char *member) const
{
  return connect(this, signal, this, member, Qt::QueuedConnection);
}

/*!
 * \brief Disconnects a signal and a slot of this object.
 *
 * \param signal the signal
 * \param member the member
 *
 * \return \c true if succeed
 */
inline bool QObjectDelegate::disconnect(const char *signal, const char *member)
{
  return QObject::disconnect(this, signal, this, member);
}

/*!
 * \brief Disconnects a signal and a slot of this object.
 *
 * \param sender the sender
 * \param signal the signal
 * \param member the member
 *
 * \return \c true if succeed
 */
inline bool QObjectDelegate::disconnect(const QObject *sender,
                                        const char *signal,
                                        const char *member)
{
  return QObject::disconnect(sender, signal, this, member);
}

// QObjectDelegate :: Protected Static Inline Member Function. -----------------

/*!
 * \brief Returns \c dispose method ID.
 *
 * \return \c dispose method ID
 */
inline jmethodID QObjectDelegate::disposeMID()
{
  return sm_disposeMID;
}

// Related Non-Member Function.  -----------------------------------------------

/*!
 * \brief Returns Cute4j delegate object for the specified QObject.
 *
 * \param qObj the QObject;
 *
 * \return Cute4j delegate object for the specified QObject
 */
template <typename T>
inline T qObjectDelegatePointer(QObject *qObj)
{
  return static_cast<T>(
      qVariantValue<QObject *>(
          qObj->property(QObjectDelegate::DELEGATE_PROPERTY_NAME)));
}

// Macro Definition. -----------------------------------------------------------

#define qObjectDelegate (reinterpret_cast<QObjectDelegate *>(delegate))

#endif // QOBJECTDELEGATE_H
